package com.itheima.jdk;

import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DemoJdkProxy {

    public static void main(String[] args) {
        //创建目标对象
        UserDao userDao = new UserDaoImpl();
        //2、创建代理对象
        /*
         * JDK动态代理：基于接口
         * 涉及到的类：
         *   Proxy
         * 涉及方法：
         *   newProxyInstance(param1,param2,param3)
         *   参数：
         *       param1:目标对象的类加载器（固定写法）
         *       param2:目标对象实现的接口(固定写法)
         *       param3:代理处理，需要程序自己手动实现
         * com.sun.proxy.$Proxy0
         * */
        UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), new InvocationHandler() {
            /**
             *
             * @param proxy     代理对象（如果不指定目标对象，则此代理对象为null）
             * @param method    执行的方法对象
             * @param args      执行方法对象的参数列表
             * @return          返回执行的方法对象的返回值，如果执行的方法是void，则此返回值可以为null
             * @throws Throwable
             *
             *          com.sun.proxy.$Proxy0 cannot be cast to com.itheima.dao.impl.UserImpl
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object obj = null;
                if (this.equals(method.getName())) {
                    return method.invoke(userDao, args);
                } else {
                    try {
                        System.out.println("前置增强"); //在目标方法之前执行，称之为前置增强
                        obj = method.invoke(userDao, args);  //执行userDao对象中带有args参数列表的method方法
                        System.out.println("后置增强");
                    } catch (Exception e) {
                        e.printStackTrace();
                        System.out.println("异常增强");
                    } finally {
                        System.out.println("最终增强");
                    }
                }
                return obj;
            }
        });

        //proxy.speck();
        proxy.save();
    }
}
